from django.shortcuts import render,redirect
from django.views.generic import View
from utils.mixin import LoginRequiredMixin
from django.http import JsonResponse
from django.urls import reverse
from user.models import Address
from goods.models import GoodsSKU
from order.models import OrderInfo, OrderGoods
from django.db import transaction
from datetime import datetime
from django_redis import get_redis_connection
import logging
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel
from alipay.aop.api.domain.AlipayTradeQueryModel import AlipayTradeQueryModel
from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest
from alipay.aop.api.request.AlipayTradeQueryRequest import AlipayTradeQueryRequest
from alipay.aop.api.response.AlipayTradeQueryResponse import AlipayTradeQueryResponse
import time
import traceback
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(message)s',
    filemode='a',)
logger = logging.getLogger('')

# Create your views here.
# /order/place
class OrderPlaceView(LoginRequiredMixin, View):
    '''提交订单类'''
    def post(self, request):
        sku_ids = request.POST.getlist('sku_ids')
        if not sku_ids:
            return redirect(reverse("cart:cart"))

        user = request.user
        addrs = Address.objects.filter(user=user)
        cart_key = 'cart_%d' % user.id
        conn = get_redis_connection('default')
        skus = []
        total_count = 0
        total_price = 0
        for sku_id in sku_ids:
            sku = GoodsSKU.objects.get(id=sku_id)
            count = conn.hget(cart_key, sku_id)
            sku.count = int(count)
            total_count += int(count)
            amount = int(count)*sku.price
            total_price += amount
            sku.amount = amount
            skus.append(sku)
        tran_price = 10
        pay_price = total_price + tran_price

        context = {
            "sku_ids": ','.join(sku_ids),
            "addrs": addrs,
            "skus": skus,
            "total_count": total_count,
            "total_price": total_price,
            "pay_price": pay_price,
            "tran_price": tran_price
        }

        return render(request, 'place_order.html', context)

# /order/save

class OrderSaveView(View):
    '''提交订单类'''
    @transaction.atomic
    def post(self, request):
        addr_id = request.POST.get("addr_id")
        pay_method = request.POST.get('pay_method')
        sku_ids = request.POST.get('sku_ids')

        user =request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '未登录'})

        if not all([addr_id, pay_method, sku_ids]):
            return JsonResponse({'res': -1, 'errmsg': '数据不完整'})

        if pay_method not in OrderInfo.PAY_METHODS.keys():
            return JsonResponse({'res': -1, 'errmsg': '支付方式非法'})
        try:
            address = Address.objects.get(id=addr_id)
        except Address.DoesNotExist:
            return JsonResponse({'res': -1, 'errmsg': '地址非法'})

        sid = transaction.savepoint()

        try:
            order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id)
            print("order_id:", order_id)
            total_count = 0
            total_price = 0
            transit_price = 10

            orderInfo = OrderInfo.objects.create(order_id=order_id, user=user,
                                     addr=address, total_count=total_count,
                                     total_price=total_price, transit_price=transit_price,
                                     pay_method=pay_method)


            conn = get_redis_connection('default')
            cart_key = 'cart_%d' % user.id
            skus_ids = sku_ids.split(",")
            for sku_id in skus_ids:
                try:
                    # 悲观锁
                   sku = GoodsSKU.objects.select_for_update().get(id=sku_id)
                except GoodsSKU.DoesNotExist:
                    return JsonResponse({'res': -1, 'errmsg': '找不到这件商品'})

                # 获取购物车商品数量
                count = conn.hget(cart_key, sku.id)
                amount = int(count)*sku.price

                if int(count) > sku.stock:
                    return JsonResponse({'res': -1, 'errmsg': "%s没有库存" % sku.name})

                # 更新库存和销量
                sku.stock -= int(count)
                sku.sales += int(count)
                sku.save()

                # 创建订单商品详情
                OrderGoods.objects.create(order=orderInfo, sku=sku, count=count, price=sku.price)

                # 计算总商品件数和总金额
                total_count += int(count)
                total_price += amount
            # 更新订单商品总数和商品总金额
            orderInfo.total_count = total_count
            orderInfo.total_price = total_price
            orderInfo.save()

            # 清空购物车
            conn.hdel(cart_key, *skus_ids)
            transaction.savepoint_commit(sid)

            return JsonResponse({'res': 1, 'msg': "订单提交成功"})

        except Exception as e:
            transaction.savepoint_rollback(sid)
            return JsonResponse({'res': -1, 'errmsg': "订单提交失败"})

class OrderPayView(View):
    def post(self, request):
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '未登录'})

        order_id = request.POST.get('order_id')

        if not all([order_id]):
            return JsonResponse({'res': -1, 'errmsg': '订单号异常'})

        try:
            orderInfo = OrderInfo.objects.get(order_id=order_id, is_delete=False, user=user, order_status=1)
        except OrderInfo.DoesNotExist:
            return JsonResponse({'res': -1, 'errmsg': '订单号异常'})

        if orderInfo.pay_method == 3:
            """
               设置配置，包括支付宝网关地址、app_id、应用私钥、支付宝公钥等，其他配置值可以查看AlipayClientConfig的定义。
            """
            alipay_client_config = AlipayClientConfig()
            alipay_client_config.server_url = 'https://openapi.alipaydev.com/gateway.do'
            alipay_client_config.app_id = '2016101900720221'
            alipay_client_config.app_private_key = 'MIIEpAIBAAKCAQEAun5v/tJ60CQ7Wn0MGbsDAac/bdS9BAC9IpnrnaaIJZVNSVB7oKPUm9EDPzbKO3AtsPVplnpVAF3fEkh3X0ziqLFajknL2HZZEVvDo4xG6xFRpU6Wx5BgTJCmTKoXJPA5eTALXW2/xGR4gZ//MfmA9+lO7LlZDYAFsOWwe/q3NdT3rkRU5SRnKxQR+pa61NaHvOa1Q97fV4shtK58bxhWyGhQZuptdhff760feifkVyTH/ZtZs0TLpoXkJqIJEi7SSMI1vfJO6n8QXUrzBfm5eEVEFan61AgyHBeEGF6oGFpeVIXo8v+GNM/n9p7/rbR2E+CcRAd8PgZXjJXPDg9EIQIDAQABAoIBAQC5iDYFLgKOda0yrbrPElTAXVHmA0Hz7IQ9GyHjWhySP0F/UXlcbACE72AqkGiKz2Q1a0EbOiK8Vacp+jv/7G6F4sMzUUlh1QNxGHi+iTy4eSdfrJqmeQTExxcaqBCUaATVgq2byiaAzG9yjekFH7JlcI9bRF3K53VB8pAsF1YTT1RDveiKT961IOOxpbYjAFROJiZbz96PUQAJS9UuDZgs7A0+Y4i9qlMERaMtPLa3/+eRXk+t+GP1CYNOjJg9C6HsSlavuxTWkhVp6dBQy8oHrGBn2aD/PAgj7/qVtv/ginWNU0xFR9WeZgXLVB9EStdY26o53zWoXaQuYALkwEFBAoGBANrp2MiuHOpiAGBwp0act/e+oB+SwOwyc5IUks12FszXhOqJepr4iiBIcALeIAmmdiYrVtEQmwn4Kc5x+r/V9Cu3GseIKM7FIrzMxr3eMms21fyegl2PbR6tXQubWvY/3DkZDOgW/u7yWGoRbDbDO8AHY6IiDWSYr6RZlE2/vVHZAoGBANoWkoU8n3DMTFZIRJqG1bfLMOGdGV6+jQPj3QH9Z44BuVVTORlSmSL2X6GaOpeGjYy0MhFHQlyk7TJjWVrbydMTUdyXBbveU+V7m3SHmFWYoqoHrdUbP5qkwHfcfs1QHEZNOIRfjKe97mE1FQcl+vDYMB3ee87f95Rvfe/XEM+JAoGALNOt3IoqyaP/x7/JwR/eXBDg4RZAAx3hpIwp84C28oM/aHd2b71tK2cp6Kxriw5XK0G8qVrpJIV4qhmU6yt4sGryROGQ2aZskpSsLb0OPf4gm3Yp49a21Y1SfEn3um0hP1/t0KjE01E04aNnsV8RISViNZUbgPnzHYhqYfFdZyECgYEApDuFYXKyuxYOkpdfmmLZxMvuZqiQt2mV9gz9nQcAmc8wi1Hd2PT7v3l7sM3dO8inBgOZBKv+DJhiy6RHYQXM6fhNmGnedojJ8zHvcoS+Mg98x8B6ptYbQtC45EqW7vRaJpL2cbEm0hdU0b1QtY5jeEXFjmjCIZtF7XE8jIYP8ckCgYAfOuus8Tyacrlb1JQFkdwB/gnbdVzyyH84a7laVukkWpfIqiAH6hD27/u2fFoidNUOZSww5bFp0EETLQ4+p6XhR4s34MxLDvnLaGa4GAfPRRA7EDAGYEPTv0nlKsKhSUyjMEQm9W/xSstimWuno+b57OTN9GpQhyYkVOYkdyvOtA=='
            alipay_client_config.alipay_public_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIgHnOn7LLILlKETd6BFRJ0GqgS2Y3mn1wMQmyh9zEyWlz5p1zrahRahbXAfCfSqshSNfqOmAQzSHRVjCqjsAw1jyqrXaPdKBmr90DIpIxmIyKXv4GGAkPyJ/6FTFY99uhpiq0qadD/uSzQsefWo0aTvP/65zi3eof7TcZ32oWpwIDAQAB'

            """
            得到客户端对象。
            注意，一个alipay_client_config对象对应一个DefaultAlipayClient，定义DefaultAlipayClient对象后，alipay_client_config不得修改，如果想使用不同的配置，请定义不同的DefaultAlipayClient。
            logger参数用于打印日志，不传则不打印，建议传递。
            """
            client = DefaultAlipayClient(alipay_client_config=alipay_client_config, logger=logger)

            """
           页面接口示例：alipay.trade.page.pay
           """
            # 对照接口文档，构造请求对象
            model = AlipayTradePagePayModel()
            model.out_trade_no = orderInfo.order_id
            model.total_amount = str(orderInfo.total_price + orderInfo.transit_price)
            model.subject = "天天生鲜%s" % orderInfo.order_id
            model.body = "支付宝测试"
            model.product_code = "FAST_INSTANT_TRADE_PAY"
            request = AlipayTradePagePayRequest(biz_model=model)
            # 得到构造的请求，如果http_method是GET，则是一个带完成请求参数的url，如果http_method是POST，则是一段HTML表单片段
            response_url = client.page_execute(request, http_method="GET")
            print("alipay.trade.page.pay response:" + response_url)
            return JsonResponse({'res': 1, 'msg': '请求成功', 'response_url': response_url})
        else:
            return JsonResponse({'res': 1, 'msg': '请求成功'})


class CheckPayView(View):
    def post(self, request):

        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '未登录'})

        order_id = request.POST.get('order_id')

        if not all([order_id]):
            return JsonResponse({'res': -1, 'errmsg': '订单号异常'})

        try:
            orderInfo = OrderInfo.objects.get(order_id=order_id, is_delete=False, user=user, order_status=1)
        except OrderInfo.DoesNotExist:
            return JsonResponse({'res': -1, 'errmsg': '订单号异常'})

        if orderInfo.pay_method == 3:
            """
               设置配置，包括支付宝网关地址、app_id、应用私钥、支付宝公钥等，其他配置值可以查看AlipayClientConfig的定义。
            """
            alipay_client_config = AlipayClientConfig()
            alipay_client_config.server_url = 'https://openapi.alipaydev.com/gateway.do'
            alipay_client_config.app_id = '2016101900720221'
            alipay_client_config.app_private_key = 'MIIEpAIBAAKCAQEAun5v/tJ60CQ7Wn0MGbsDAac/bdS9BAC9IpnrnaaIJZVNSVB7oKPUm9EDPzbKO3AtsPVplnpVAF3fEkh3X0ziqLFajknL2HZZEVvDo4xG6xFRpU6Wx5BgTJCmTKoXJPA5eTALXW2/xGR4gZ//MfmA9+lO7LlZDYAFsOWwe/q3NdT3rkRU5SRnKxQR+pa61NaHvOa1Q97fV4shtK58bxhWyGhQZuptdhff760feifkVyTH/ZtZs0TLpoXkJqIJEi7SSMI1vfJO6n8QXUrzBfm5eEVEFan61AgyHBeEGF6oGFpeVIXo8v+GNM/n9p7/rbR2E+CcRAd8PgZXjJXPDg9EIQIDAQABAoIBAQC5iDYFLgKOda0yrbrPElTAXVHmA0Hz7IQ9GyHjWhySP0F/UXlcbACE72AqkGiKz2Q1a0EbOiK8Vacp+jv/7G6F4sMzUUlh1QNxGHi+iTy4eSdfrJqmeQTExxcaqBCUaATVgq2byiaAzG9yjekFH7JlcI9bRF3K53VB8pAsF1YTT1RDveiKT961IOOxpbYjAFROJiZbz96PUQAJS9UuDZgs7A0+Y4i9qlMERaMtPLa3/+eRXk+t+GP1CYNOjJg9C6HsSlavuxTWkhVp6dBQy8oHrGBn2aD/PAgj7/qVtv/ginWNU0xFR9WeZgXLVB9EStdY26o53zWoXaQuYALkwEFBAoGBANrp2MiuHOpiAGBwp0act/e+oB+SwOwyc5IUks12FszXhOqJepr4iiBIcALeIAmmdiYrVtEQmwn4Kc5x+r/V9Cu3GseIKM7FIrzMxr3eMms21fyegl2PbR6tXQubWvY/3DkZDOgW/u7yWGoRbDbDO8AHY6IiDWSYr6RZlE2/vVHZAoGBANoWkoU8n3DMTFZIRJqG1bfLMOGdGV6+jQPj3QH9Z44BuVVTORlSmSL2X6GaOpeGjYy0MhFHQlyk7TJjWVrbydMTUdyXBbveU+V7m3SHmFWYoqoHrdUbP5qkwHfcfs1QHEZNOIRfjKe97mE1FQcl+vDYMB3ee87f95Rvfe/XEM+JAoGALNOt3IoqyaP/x7/JwR/eXBDg4RZAAx3hpIwp84C28oM/aHd2b71tK2cp6Kxriw5XK0G8qVrpJIV4qhmU6yt4sGryROGQ2aZskpSsLb0OPf4gm3Yp49a21Y1SfEn3um0hP1/t0KjE01E04aNnsV8RISViNZUbgPnzHYhqYfFdZyECgYEApDuFYXKyuxYOkpdfmmLZxMvuZqiQt2mV9gz9nQcAmc8wi1Hd2PT7v3l7sM3dO8inBgOZBKv+DJhiy6RHYQXM6fhNmGnedojJ8zHvcoS+Mg98x8B6ptYbQtC45EqW7vRaJpL2cbEm0hdU0b1QtY5jeEXFjmjCIZtF7XE8jIYP8ckCgYAfOuus8Tyacrlb1JQFkdwB/gnbdVzyyH84a7laVukkWpfIqiAH6hD27/u2fFoidNUOZSww5bFp0EETLQ4+p6XhR4s34MxLDvnLaGa4GAfPRRA7EDAGYEPTv0nlKsKhSUyjMEQm9W/xSstimWuno+b57OTN9GpQhyYkVOYkdyvOtA=='
            alipay_client_config.alipay_public_key = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnMB7EFoAdhsL49bCDGDoWBC96oPoXaTMaT8kLBklhJI162byN1PW+rTYTY6Y65u0hqOFYOl2AKCyhHX3GOth7Tvb/ce6iS57fEwkHkDCEyJ5/la/3qA0sLx3m3dK+pSqaVXAx8HczRJtjGRzNOT285qcieHvHIZEzYuPWi1kFppw2RG4gJFIaieb41wA2x4HDOcZ85osibwXQXbXzI36+fTRa0FTjO+11epQWy0TPvpQSBQeWaS154Prqtv1WyJ5zpR5M23zMy75CgxNbdnuHq5UneLC0dYmxrkDVJ3hDGvgmNT06Z485YsgSwy1kCKtAV2fqUQChFfzAkFQ+B21awIDAQAB'

            """
            得到客户端对象。
            注意，一个alipay_client_config对象对应一个DefaultAlipayClient，定义DefaultAlipayClient对象后，alipay_client_config不得修改，如果想使用不同的配置，请定义不同的DefaultAlipayClient。
            logger参数用于打印日志，不传则不打印，建议传递。
            """
            client = DefaultAlipayClient(alipay_client_config=alipay_client_config, logger=logger)

            """
                系统接口：alipay.trade.query
            """
            model = AlipayTradeQueryModel()
            model.out_trade_no = str(order_id)

            request = AlipayTradeQueryRequest(biz_model=model)

            response_content = None
            while True:
                try:
                    response_content = client.execute(request)
                except Exception as e:
                    continue

                if not response_content:
                    return JsonResponse({'msg': -1, 'errmsg': '请求失败'})
                else:
                    response = AlipayTradeQueryResponse()
                    # # 解析响应结果
                    response.parse_response_content(response_content)
                    print(response.body)
                    if response.is_success():
                        # 如果业务成功，则通过respnse属性获取需要的值
                        print("get response trade_no:" + response.trade_no)
                        orderInfo.order_status = 4
                        orderInfo.trade_no = response.trade_no
                        orderInfo.save()
                        return JsonResponse({'msg': 1, 'errmsg': '支付成功'})
                    elif response.code == 40004 or (response.code == 10000 and response.trade_status == 'WAIT_BUYER_PAY'):
                        time.sleep(2)
                        continue
                    else:
                        # 如果业务失败，则从错误码中可以得知错误情况，具体错误码信息可以查看接口文档
                        print(response.code + "," + response.msg + "," + response.sub_code + "," + response.sub_msg)
                        return JsonResponse({'msg': -1, 'errmsg': response.msg})
